<template>
  <div ref="threeContainer" class="three-container"></div>
</template>

<script>
import * as THREE from 'three';
import { createNoise2D } from 'simplex-noise';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';

export default {
  name: 'FireFly',
  data() {
    return {
      scene: null,
      camera: null,
      renderer: null,
      composer: null,
      particles: null,
      noise: createNoise2D(),
      time: 0,
      animationFrameId: null
    };
  },
  mounted() {
    this.initScene();
    this.animate();
  },
  beforeDestroy() {
    this.destroyScene();
  },
  methods: {
    initScene() {
      // 创建场景
      this.scene = new THREE.Scene();

      // 创建摄像机
      this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 20, 1000);
      this.camera.position.set(0, 150, 500);
      this.camera.lookAt(0, 0, 0);

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.$refs.threeContainer.appendChild(this.renderer.domElement);

      // 创建粒子系统
      this.particles = new THREE.Group();
      const particlesCount = 200;

      for (let i = 0; i < particlesCount; i++) {
        const geometry = new THREE.SphereGeometry(5, 5, 5); //创建球体
        const material = new THREE.MeshStandardMaterial({
          emissive: new THREE.Color("#CCFF00"), //自发光颜色
          emissiveIntensity: 1.5, //自发光强度
        });
        const particle = new THREE.Mesh(geometry, material);

        // 设置萤火虫的随机位置
        particle.position.x = Math.random() * 1000 - 500;
        particle.position.y = Math.random() * 1000 - 500;
        particle.position.z = Math.random() * 1000 - 500;

        this.particles.add(particle);
      }
      this.scene.add(this.particles);

      // 添加光源
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
      this.scene.add(ambientLight);

      const pointLight = new THREE.PointLight(0xffffff, 1.5, 1000);
      pointLight.position.set(200, 300, 400);
      this.scene.add(pointLight);

      // 添加相机控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enabled = true;
      this.controls.update();

      // 初始化后期处理
      this.initPostProcessing();

      // 处理窗口大小变化
      window.addEventListener('resize', this.onWindowResize);
    },

    initPostProcessing() {
      this.composer = new EffectComposer(this.renderer);

      // 场景渲染 Pass
      const renderPass = new RenderPass(this.scene, this.camera);
      this.composer.addPass(renderPass);

      // 光晕效果 Pass
      const bloomPass = new UnrealBloomPass(
        new THREE.Vector2(window.innerWidth, window.innerHeight),
        1.5,
        0.3,
        0.25
      );
      this.composer.addPass(bloomPass);
    },

    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.composer.setSize(window.innerWidth, window.innerHeight);
    },

    updateParticles() {
      this.particles.children.forEach((particle) => {
        const { x, y, z } = particle.position;

        // 使用噪声来更新粒子的位置
        particle.position.x += this.noise(x, this.time) * 3;
        particle.position.y += this.noise(y, this.time) * 3;
        particle.position.z += this.noise(z, this.time) * 3;
      });

      this.time += 0.1;
    },

    animate() {
      this.animationFrameId = requestAnimationFrame(this.animate);
      this.updateParticles();
      this.composer.render();
    },

    destroyScene() {
      cancelAnimationFrame(this.animationFrameId);
      if (this.composer) this.composer.dispose();
      if (this.renderer) this.renderer.dispose();
      window.removeEventListener('resize', this.onWindowResize);
    }
  }
};
</script>

<style scoped>
.three-container {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  overflow: hidden;
}
</style>